<script setup lang="ts">
import Grid from "@/components/framework/grid.vue";
import CustomIcon from "@/components/framework/icon";
import { computed, onBeforeMount, ref, shallowReactive, shallowRef, watch } from "vue";
import { LanShare } from "@/ipc/lan-share.ts";
import type { LanShareServerStatus, ShareFileInfo } from "@common/lan-share-types.ts";
import { showMessageAndPrint } from "@/framework/util/log.ts";
import ScrollView from "@/components/framework/scroll-view.vue";
import { hc } from "@/framework/vue/util/render.ts";
import {
  CopyOutlined,
  DeleteOutlined,
  ExportOutlined,
  FileAddFilled,
  FileFilled,
  FolderAddFilled,
  FolderFilled,
  PauseCircleFilled,
  PlayCircleFilled,
} from "@ant-design/icons-vue";
import { ulid } from "ulid";
import { message } from "ant-design-vue";
import { copyText } from "@/util/clipboard.ts";

const fileList = shallowReactive<ShareFileInfo[]>([]);
const serverStatus = shallowRef<LanShareServerStatus>();

const selectedHost = ref<string>();
const hostsOptions = computed(() => (serverStatus.value?.hosts || []).map(it => ({ value: it })));
watch(
  hostsOptions,
  options => {
    if (!selectedHost.value || !options.find(it => it.value === selectedHost.value)) {
      selectedHost.value = options[0]?.value ?? "";
    }
  },
  { immediate: true },
);

const serverUrl = computed(() => `http://${selectedHost.value}:${serverStatus.value?.port}`);

const loadServerStatus = () => {
  LanShare.getStatus().then(status => {
    serverStatus.value = status;
  });
};

onBeforeMount(() => {
  loadServerStatus();

  LanShare.getSharedFiles()
    .then(list => fileList.push(...list))
    .catch(showMessageAndPrint);
});

const startServer = () => {
  LanShare.startServer()
    .then(status => {
      message.success("服务已启动");
      serverStatus.value = status;
    })
    .catch(showMessageAndPrint);
};

const stopServer = () => {
  LanShare.stopServer()
    .then(status => {
      serverStatus.value = status;
    })
    .catch(showMessageAndPrint);
};

const openLink = () => native.shell.openExternal(serverUrl.value);
const copyLink = () => copyText(serverUrl.value);

const addItems = async (filePaths: string[], type: "file" | "dir") => {
  for (const filePath of filePaths) {
    if (!fileList.find(it => it.path === filePath)) {
      const fileInfo: ShareFileInfo = { id: ulid(), path: filePath, type };
      fileList.unshift(fileInfo);
      await LanShare.addShareFile(fileInfo);
    }
  }
};

const pickFile = () => {
  native.dialog
    .showOpenDialog({ title: "选择文件", properties: ["multiSelections"] })
    .then(async ret => {
      if (!ret.canceled) {
        await addItems(ret.filePaths, "file");
      }
    })
    .catch(showMessageAndPrint);
};

const pickFolder = () => {
  native.dialog.showOpenDirectoryDialog({ title: "选择文件夹", properties: ["multiSelections"] }).then(async ret => {
    if (!ret.canceled) {
      await addItems(ret.filePaths, "dir");
    }
  });
};

const deleteFile = (file: ShareFileInfo) => {
  LanShare.deleteShareFile(file.id)
    .then(() => {
      fileList.splice(fileList.indexOf(file), 1);
    })
    .catch(showMessageAndPrint);
};
</script>

<template>
  <grid class="lan-share" col-template="1fr 2fr">
    <div class="overflow-auto flex-center">
      <div class="flex-column aic row-gap-32">
        <custom-icon type="icon-lx-send" class="font-60" />
        <span class="bold font-20">文件分享</span>
        <div class="flex aic col-gap-10">
          <a-button v-if="!serverStatus?.running" :icon="hc(PlayCircleFilled)" type="primary" @click="startServer">启动服务</a-button>
          <a-button v-else :icon="hc(PauseCircleFilled)" danger @click="stopServer">关闭服务</a-button>
        </div>
        <div class="flex aic col-gap-10">
          <span>http://</span>
          <a-select v-model:value="selectedHost" :options="hostsOptions" class="w-130" />
          <span>:{{ serverStatus?.port }}</span>
          <a-button :icon="hc(ExportOutlined)" :disabled="!serverStatus?.running" type="text" shape="circle" @click="openLink" />
          <a-button :icon="hc(CopyOutlined)" :disabled="!serverStatus?.running" type="text" shape="circle" @click="copyLink" />
        </div>
        <div class="flex aic col-gap-10">
          <a-button :icon="hc(FileAddFilled)" @click="pickFile">新增文件</a-button>
          <a-button :icon="hc(FolderAddFilled)" @click="pickFolder">新增文件夹</a-button>
        </div>
      </div>
    </div>
    <div class="overflow-auto p-10">
      <scroll-view class="pv-10 border-radius">
        <template v-for="it in fileList" :key="it.id">
          <div class="share-file-item">
            <span class="file-icon">
              <FileFilled v-if="it.type === 'file'" class="color-success" />
              <FolderFilled v-else class="color-warning" />
            </span>
            <div class="flex-1 overflow-hidden">
              <span class="text-ellipsis">{{ it.path }}</span>
            </div>
            <a-button type="text" :icon="hc(DeleteOutlined)" shape="circle" danger @click="deleteFile(it)" />
          </div>
        </template>
      </scroll-view>
    </div>
  </grid>
</template>

<style lang="less">
.share-file-item {
  display: flex;
  align-items: center;
  column-gap: 10px;
  height: 35px;
  box-sizing: border-box;
  padding: 0 10px;
  margin: 0 10px;
  border-radius: var(--border-radius);
  transition: all 0.2s;
  border-bottom: 1px solid var(--border-color);

  & + .share-file-item {
    margin-top: 5px;
  }

  .file-icon {
    width: 20px;
    text-align: center;
    font-size: 20px;
  }

  &:hover {
    background-color: var(--color-bg-text-hover);
  }
}
</style>
